/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package heuristics;

/**
 *
 * @author ahmad
 */
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.Arrays;

import javax.sound.midi.Soundbank;

import misc.FOV;

import algos.Geometry;

public class CentralizedForceCoverage extends CoverageHeuristic {

    public CentralizedForceCoverage(String file, int number_of_orientations) {
        super(file, number_of_orientations);
    }

    public CentralizedForceCoverage(ArrayList<Rectangle> obstacles,
            ArrayList<Point2D.Double> cameras, ArrayList<Point2D.Double> people,
            int number_of_orientations) {
        super(obstacles, cameras, people, number_of_orientations, false);
    }

    public static double angleBetween2Lines(double[] line1, double[] line2) {
        double angle1 = Math.atan2(line1[1] - line1[3], line1[0] - line1[2]);
        double angle2 = Math.atan2(line2[1] - line2[3], line2[0] - line2[2]);
        return angle1 - angle2;
    }

    public int[] reassign() {
        computeSpotted();
        boolean[] used = new boolean[number_of_cameras];
        boolean[] covered = new boolean[number_of_men];
        assignment = new int[number_of_cameras];
        IDs = new int[number_of_cameras];
        FOV polygon;
        int greedyCoverage = 0;
        for (int i = 0; i < number_of_cameras; i++) {
            int bestCamInd = -1, bestOrient = -1, bestID = -1;
            ;
            double best = -1;
            // int minbestCamOrientId = Integer.MAX_VALUE;
            for (int camInd = 0; camInd < number_of_cameras; camInd++) {
                if (used[camInd]) {
                    continue;
                }
                int bestCamOrient = -1, bestCam = -1, totalCam = 0, minbestCamOrientId = 0;
                boolean taken[] = new boolean[number_of_men];
                Arrays.fill(taken, false);
                // int orientPersonID = -1;
                for (int orient = 0; orient < number_of_orientations; orient++) {
                    polygon = getOrientationIsovist(camInd, orient);
                    // double minAngle = 10000.0d;
                    int orientCov = 0;
                    int orientId = -1;
                    double lAngle = Geometry.computeAngle(new double[]{
                                cameras.get(camInd).x, cameras.get(camInd).y, 0},
                            new double[]{polygon.xpoints[1],
                                polygon.ypoints[1], 0}, new double[]{
                                640, cameras.get(camInd).y, 0});
                    if (polygon.ypoints[1] < cameras.get(camInd).y) {
                        lAngle = 2 * Math.PI - lAngle;
                    }
                    // lAngle = Math.toDegrees(lAngle);
                    double minAngle = 100;

                    for (int p = 0; p < number_of_men; p++) {
                        if (spotted[camInd][0][orient][p]) {
                            double pAngle = Geometry.computeAngle(new double[]{
                                        cameras.get(camInd).x,
                                        cameras.get(camInd).y, 0},
                                    new double[]{people.get(p).x, people.get(p).y, 0},
                                    new double[]{640, cameras.get(camInd).y,
                                        0});
                            if (cameras.get(camInd).y > people.get(p).y) {
                                pAngle = 2 * Math.PI - pAngle;
                            }
                            double diff = Math.abs(pAngle - lAngle);
                            if (Double.compare(diff, minAngle) < 0) {
                                minAngle = diff;
                                orientId = p;
                            }
                            if (covered[p]) {
                                continue;
                            }
                            orientCov++;
                            if (!taken[p]) {
                                totalCam++;
                                taken[p] = true;
                            }
                        }
                    }

                    if ((bestCam < orientCov)
                            || (bestCam == orientCov && orientId <= minbestCamOrientId)) {  // if tie, choose the one with the lowest ID
                        minbestCamOrientId = orientId;
                        bestCam = orientCov;
                        bestCamOrient = orient;

                    }
                }
                if (Double.compare(best, 1.0 * bestCam / totalCam) < 0) {
                    best = 1.0 * bestCam / totalCam;
                    bestOrient = bestCamOrient;
                    bestID = minbestCamOrientId;
                    bestCamInd = camInd;
                }


            }
            used[bestCamInd] = true;

            assignment[bestCamInd] = bestOrient;
            IDs[bestCamInd] = bestID;
            for (int p = 0; p < number_of_men; p++) {
                if (spotted[bestCamInd][0][bestOrient][p]) {
                    if (!covered[p]) {
                        greedyCoverage++;
                    }
                    covered[p] = true;
                }
            }
        }
        return assignment;
    }
    @Override
    public String toString() {
        return "Centralized Force";
    }
}
